package com.zds.hj.poseidon.biz.dispatcher.credit;

import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReUtil;
import com.alibaba.fastjson.JSON;
import com.zds.boot.common.exception.BusinessException;
import com.zds.boot.common.utils.Ids;
import com.zds.boot.common.utils.Strings;
import com.zds.boot.dispatch.annotation.DispatcherHandler;
import com.zds.boot.dispatch.comm.enums.InstructTypeEnum;
import com.zds.boot.dispatch.comm.enums.ModuleNodeTypeEnum;
import com.zds.boot.dispatch.dto.*;
import com.zds.hj.competency.facade.enums.TencentApiTypeEnum;
import com.zds.hj.icmc.facade.auth.assetcenter.dto.req.FourElementsVerifyReqDto;
import com.zds.hj.icmc.facade.auth.assetcenter.dto.resp.AuthRespDto;
import com.zds.hj.icmc.facade.auth.assetcenter.dto.resp.FourElementsVerifyRespDto;
import com.zds.hj.icmc.facade.auth.assetcenter.enums.AuditStatusEnum;
import com.zds.hj.icmc.facade.dto.file.FileUploadResultDto;
import com.zds.hj.poseidon.biz.cba.hpp.domain.credit.service.layout.CreditApplyService;
import com.zds.hj.poseidon.biz.common.IcmcServiceInterface;
import com.zds.hj.poseidon.biz.common.helper.FileUploadTransService;
import com.zds.hj.poseidon.facade.dto.hpp.credit.CreditInfoEntityDto;
import com.zds.hj.product.facade.constant.ApplicationContainerConstant;
import com.zds.zly.common.enums.HjResultCodeEnum;
import com.zds.zly.common.utils.EmptyChecker;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author:hfy
 * @Date:2023/06/06/14:39
 * @Description: 授信阶段——用户四要素认证
 * 可逆 不可异步 不是自动节点
 * 个人四要素验证，校验法人姓名，身份证，银行卡号，手机号是否一致，发送短信功能,执行时校验，短信错误直接抛出异常提示，
 * 个人四要素信息不正确，也抛出异常提示
 */
@DispatcherHandler(value = "AuthPersonFoursCheckHandler", desc = "用户四要素认证",
        nodeType = ModuleNodeTypeEnum.BUSINESS,
        applicationContainer = ApplicationContainerConstant.FRONT_END)
@Slf4j
public class AuthPersonFoursCheckHandler extends CreditCheckAbsHandler {
    @Resource
    private CreditApplyService creditApplyService;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private FileUploadTransService fileUploadTransService;
    @Resource
    private IcmcServiceInterface icmcServiceInterface;

    @Override
    public void creditDoExecute(BaseReqModel params, BaseResultModel resultModel,
                                CreditInfoEntityDto reqData, CreditInfoEntityDto dbData) {
        System.out.println(reqData);
        //四要素验证
        if (EmptyChecker.isEmpty(reqData.getName())) {
            throw new BusinessException("姓名不能为空", HjResultCodeEnum.PARAMS_VALIDATE_FAIL.code());
        }
        if (EmptyChecker.isEmpty(reqData.getCardId())) {
            throw new BusinessException("身份证号不能为空", HjResultCodeEnum.PARAMS_VALIDATE_FAIL.code());
        }
        if (EmptyChecker.isEmpty(reqData.getCardNo())) {
            throw new BusinessException("银行卡号不能为空", HjResultCodeEnum.PARAMS_VALIDATE_FAIL.code());
        }
        if (EmptyChecker.isEmpty(reqData.getPhone())) {
            throw new BusinessException("手机号不能为空", HjResultCodeEnum.PARAMS_VALIDATE_FAIL.code());
        }
        if (EmptyChecker.isEmpty(reqData.getCode())) {
            throw new BusinessException("验证码不能为空", HjResultCodeEnum.PARAMS_VALIDATE_FAIL.code());
        }
        //身份证号是否合法
        if (!IdcardUtil.isValidCard(reqData.getCardId())) {
            throw new BusinessException("身份证号格式不正确", HjResultCodeEnum.PARAMS_VALIDATE_FAIL.code());
        }
        if (!ReUtil.isMatch("^[1-9]\\d{9,29}$", reqData.getCardNo())) {
            throw new BusinessException("银行卡号格式不正确", HjResultCodeEnum.PARAMS_VALIDATE_FAIL.code());
        }
        if (!ReUtil.isMatch("^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$",
                reqData.getPhone())) {
            throw new BusinessException("手机号格式不正确", HjResultCodeEnum.PARAMS_VALIDATE_FAIL.code());
        }
        //短信验证码检查
        Object o = redisTemplate.opsForValue().get(reqData.getPhone());

        if (!Strings.equals(reqData.getCode(), String.valueOf(o))) {
            throw new BusinessException("验证码错误", HjResultCodeEnum.PARAMS_VALIDATE_FAIL.code());
        }
        // 调用第三方接口验证身份证、银行卡、手机号是否对应
        FourElementsVerifyReqDto fourElementsVerifyReqDto = new FourElementsVerifyReqDto();
        fourElementsVerifyReqDto.setPersonBankAccount(reqData.getCardNo());
        fourElementsVerifyReqDto.setPersonCardNo(reqData.getCardId());
        fourElementsVerifyReqDto.setPersonName(reqData.getName());
        fourElementsVerifyReqDto.setPersonTelphone(reqData.getPhone());
        fourElementsVerifyReqDto.setPersonCardType("0");
        fourElementsVerifyReqDto.setChannelNo(reqData.getChannelNo());
        fourElementsVerifyReqDto.setThirdSerialNo(dbData.getApplyNo());
        AuthRespDto<FourElementsVerifyRespDto> respDto =
                icmcServiceInterface.fourElementsVerify(fourElementsVerifyReqDto);
        //认证失败
        if (!AuditStatusEnum.AUDIT_PASSED.code().equals(respDto.getAuditStatusEnum().code())){
            throw new BusinessException("个人四要素信息不正确", HjResultCodeEnum.PARAMS_VALIDATE_FAIL.code());
        }
        //验证通过
        resultModel.setResult("认证成功");
        dbData.setName(reqData.getName());
        dbData.setAddress(reqData.getAddress());
        dbData.setCardId(reqData.getCardId());
        dbData.setPhone(reqData.getPhone());
        dbData.setCardFrontObsId(reqData.getCardFrontObsId());
        dbData.setCardBackObsId(reqData.getCardBackObsId());
        dbData.setCardNo(reqData.getCardNo());
    }

    @Override
    public Object echoDetail(BaseReqModel params) {
        HashMap<String, Object> resultMap = new HashMap<>();
        List<InstructDto> instructSettingDtoList = params.getDispatchModuleNodes().getInstructSettingDtos();
        Map<String, String> instructSettingMap = instructSettingDtoList.stream().collect(Collectors.toMap(InstructDto::getInstructCode, InstructDto::getValues));
        //判断是否回显
        String isBackShow = instructSettingMap.get("isBackShow");
        if ("是".equals(isBackShow)){
            //查询信息
            CreditInfoEntityDto creditOnTransit = creditApplyService.findCreditOnTransit(params);
            if (EmptyChecker.notEmpty(creditOnTransit.getCardFrontObsId())){
                resultMap.put("idenFront",creditOnTransit.getCardFrontObsId());
            }
            if (EmptyChecker.notEmpty(creditOnTransit.getCardBackObsId())){
                resultMap.put("idenReserve",creditOnTransit.getCardBackObsId());
            }
            if (EmptyChecker.notEmpty(creditOnTransit.getAddress())){
                resultMap.put("address",creditOnTransit.getAddress());
            }
            if (EmptyChecker.notEmpty(creditOnTransit.getName())){
                resultMap.put("name", creditOnTransit.getName());
            }
            if (EmptyChecker.notEmpty(creditOnTransit.getCardId())){
                resultMap.put("cardId", creditOnTransit.getCardId());
            }
        }
        return resultMap;
    }

    @Override
    public List<InstructRegisterModule> moduleInstructs() {
        List<InstructRegisterModule> instructRegisterModules = new ArrayList<>();
        InstructRegisterModule registerModule0 = new InstructRegisterModule();
        registerModule0.setInstructCode("isBackShow");
        registerModule0.setInstructName("是否反显信息");
        registerModule0.setInstructTitle("是否反显信息");
        registerModule0.setInstructType(InstructTypeEnum.PULL_DOWN_ONE);
        registerModule0.setInstructEmphatic("是否反显信息");
        registerModule0.setEmptyCheck(true);
        registerModule0.setValueSource(1);
        registerModule0.setInstructValueByCustom("是^否");
        instructRegisterModules.add(registerModule0);
        return instructRegisterModules;
    }

    @Override
    public Object paramsFerry(Object o) {
        CreditInfoEntityDto dbDto = (CreditInfoEntityDto) o;
        CreditInfoEntityDto creditInfoEntityDto = new CreditInfoEntityDto();
        creditInfoEntityDto.setName(dbDto.getName());
        creditInfoEntityDto.setCardNo(dbDto.getCardNo());
        creditInfoEntityDto.setPhone(dbDto.getPhone());
        creditInfoEntityDto.setAddress(dbDto.getAddress());
        creditInfoEntityDto.setCardId(dbDto.getCardId());
        creditInfoEntityDto.setCode(dbDto.getCode());
        return creditInfoEntityDto;
    }

    @Override
    public BaseResultModel doSection(BaseReqModel baseReqModel) {
        BaseResultModel baseResultModel = super.doSection(baseReqModel);
        String type = baseReqModel.getHttpServletRequest().getParameter("type");
        if (Strings.isBlank(type)){
            return baseResultModel;
        }
        //分段提交身份证正面、反面图片
        //查询在途订单
        CreditInfoEntityDto creditOnTransit = creditApplyService.findCreditOnTransit(baseReqModel);
        FileUploadResultDto fileUploadResultDto = fileUploadTransService.fileTransFromObs(baseReqModel
                .getHttpServletRequest());
        //身份证正面 保存个人信息
        if (TencentApiTypeEnum.OCR_ID_CARD.code().equals(type)){
            creditOnTransit.setAddress(fileUploadResultDto.getApplyAddressDetail());
            creditOnTransit.setName(fileUploadResultDto.getName());
            creditOnTransit.setCardId(fileUploadResultDto.getPicNo());
            creditOnTransit.setCardFrontObsId(fileUploadResultDto.getFileId());
            //身份证反面 保存图片id
        }else if (TencentApiTypeEnum.OCR_ID_CARD_B.code().equals(type)){
            creditOnTransit.setCardBackObsId(fileUploadResultDto.getFileId());
        }
        if (TencentApiTypeEnum.OCR_ID_CARD.code().equals(type) ||
                TencentApiTypeEnum.OCR_ID_CARD_B.code().equals(type)){
            creditApplyService.update(baseReqModel, creditOnTransit);
        }
        baseResultModel.setResult(fileUploadResultDto);
        return baseResultModel;
    }

    @Override
    public Object preHanding(BaseReqModel params) {
        return super.preHanding(params);
    }

    @Override
    public Object redoPreHanding(BaseReqModel params) {
        //重新发送短信
        CreditInfoEntityDto reqDto =  JSON.parseObject(JSON.toJSONString(params.getRequest()), CreditInfoEntityDto.class);
        if (EmptyChecker.isEmpty(reqDto.getPhone())){
            throw new BusinessException("手机号不能为空", HjResultCodeEnum.NO_DATA_FOUND.code());
        }
        String phone = reqDto.getPhone();
        CreditInfoEntityDto credit = creditApplyService.findCreditOnTransit(params);
        if (EmptyChecker.isEmpty(credit)) {
            throw new BusinessException("授信信息不存在", HjResultCodeEnum.PARAMS_VALIDATE_FAIL.code());
        }
        if (!ReUtil.isMatch("^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$",
                phone)) {
            throw new BusinessException("手机号格式不正确", HjResultCodeEnum.PARAMS_VALIDATE_FAIL.code());
        }
        String code = RandomUtil.randomNumbers(6);
        //存入redis 生命周期5分钟
        redisTemplate.opsForValue().set(phone, code, 5, TimeUnit.MINUTES);
        log.info("预处理发送短信,手机号:{}, 验证码: {}", phone, code);
        //返回验证码
        return code;
    }


}
